/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 * Lua script operator
 * 
 * Lua 5.1.4 works fine here, I am working for the new 5.2.0 stable version out
 * We should run 'autoreconf' to enable Lua supporting in configure.ac
 * 
 * ADDITIONAL FILE OF id5db
 * By Dr.NP <np@bsgroup.org>
 */

#include "memcached.h"
#include "id5db_script.h"
#include "id5db_misc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

lua_State *base_state = NULL;

static void clear_state()
{
    if (base_state)
    {
        lua_settop(base_state, 0);
    }
    
    return;
}

static int func_mysql_query(lua_State *l)
{
    size_t len;
    char *query = strdup(lua_tolstring(l, -1, &len));
    int res = -1;
    
    if (query && len > 0)
    {
        res = id5db_mysql_query(query, len);
    
        free(query);
    }
    
    lua_pushinteger(l, res);
    
    return 1;
}

// Init Lua state, load script file and parse it
lua_State * id5db_script_init(const char *script_filename)
{
    base_state = luaL_newstate();
    if (base_state)
    {
        luaL_openlibs(base_state);
        if (luaL_loadfile(base_state, script_filename) != 0 || lua_pcall(base_state, 0, 0, 0) != 0)
        {
            fprintf(stderr, "Load lua script %s error : %s\n", script_filename, lua_tostring(base_state, -1));
            exit(1);
        }
        
        lua_pushcfunction(base_state, func_mysql_query);
        lua_setglobal(base_state, "id5db_mysql_query");
    }
    
    return base_state;
}

// Get config value from script
char * id5db_script_get_config(const char *key)
{
    if (!base_state)
    {
        return NULL;
    }
    
    lua_getglobal(base_state, CONFIG_TABLE_NAME);
    if (!lua_istable(base_state, -1))
    {
        fprintf(stderr, "Global table <%s> not set in lua script, please check if you load a wrong script file??\n", CONFIG_TABLE_NAME);
        return "";
    }
    
    lua_pushstring(base_state, key);
    lua_gettable(base_state, -2);
    if (!lua_isstring(base_state, -1))
    {
        // Configuration value must be a string
        return "";
    }
    
    // We have to copy the string from stack
    char *value = strdup(lua_tostring(base_state, -1));
    lua_pop(base_state, -1);
    
    return value;
}

// Call function to rebuild string
void id5db_script_call_fun(uint64_t id, const char *data, size_t len)
{
    if (!base_state)
    {
        return;
    }
    
    lua_getglobal(base_state, REBUILD_FUN);
    lua_pushnumber(base_state, id);
    lua_pushlstring(base_state, data, len);
    if (0 != lua_pcall(base_state, 2, 0, 0))
    {
        // Call function error
        fprintf(stderr, "%s\n", lua_tostring(base_state, -1));
        clear_state();
        
        return;
    }
    
    clear_state();
    
    return;
}

/* *** Ext functions *** */
